package gl.java.umsp.bean;

import com.chanceit.framework.utils.encode.Des;
import com.google.gson.Gson;
import gl.java.umsp.room.RoomServiceConfig;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

@EqualsAndHashCode(callSuper = true)
@Slf4j
public @Data
class Room extends JsonBean {
    private transient volatile AtomicInteger roomIndex = new AtomicInteger();
    private static final String DES_KEY_DEFAULT = "Room-DES-KEY";
    private static final String SPLIT_CHAR = "##";
    public String roomID = "0000-0000-0000-0000";
    public String roomIP = "127.0.0.1";
    public int roomPort = 8899;
    public String roomURL = roomIP + ":" + (roomPort - 1) + "/ws";
    public int gameID;
    public transient static Map<Integer, RoomServiceConfig> map = new ConcurrentHashMap<Integer, RoomServiceConfig>();

    /**
     * 房间名
     */
    public String roomName;
    /**
     * 房间密码
     */
    public String passWord;
    /**
     * 回话ID生成key
     */
    private static String sessionGenKey = DES_KEY_DEFAULT;
    public String session = "";

    /**
     * 房间人数上线
     */
    public int maxRoomUser = 2;
    /**
     * 状态枚举见{@link RoomPlayerState}
     */
    public int roomState;
    /**
     * 已经在房间中的用户
     */
    private Map<Integer, User> roomUserList = new ConcurrentHashMap<Integer, User>();
    /**
     * 游戏开始后从房间中延迟移除掉线玩家的时长,单位ms </br>
     * 期间保留用户信息;0表示掉线立刻移除
     */
    public long delayForRemoveOfflineUser = 0;

    /**
     * 被分配进入该房间的用户列表,但用户不一定会进入这个房间.中间有一个进入过程
     *
     * @see #roomUserList
     */
    private Map<Integer, User> beMatchedInThisRoomUserList = new ConcurrentHashMap<Integer, User>();
    /**
     * 将用户优先匹配到这个房间的匹配权重,数值越大.优先级越高
     */
    public int matchWeight;

    /**
     * 房间额外的信息
     */
    public String extraInfo;

    /**
     * 房间循环
     */
    public transient Object loop = new Object();


    public Room(int gameID) {
        this.gameID = gameID;
        this.roomID = UUID.randomUUID().toString();
        this.roomName =
                String.valueOf(roomIndex.getAndIncrement());
        log.info("# create room # roomName:" + roomName + " room:" + roomID);
        this.session = Room.genSession(this);
        this.initServerAddress();
    }

    public Room(int gameID, String roomID, String session) {
        this.session = session;
        this.roomID = roomID;
        this.gameID = gameID;
        this.initServerAddress();
    }

    private void initServerAddress() {
        RoomServiceConfig m_server_reg_room = this.map.get(this.gameID);
        if (m_server_reg_room == null) {
            return;
        }
        this.roomIP = m_server_reg_room.IP;
        this.roomPort = m_server_reg_room.port;
        this.roomURL = roomIP + ":" + m_server_reg_room.portWebSocket + "/ws";
    }

    @Override
    public String toString() {
        return new Gson().toJson(this);
    }

    public static String genSession(Room room) {
        try {
            return Des.enCrypto(room.getRoomID() + SPLIT_CHAR + room.getGameID(), room.sessionGenKey);
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("fail genSession,case:" + e.getMessage());
        }
        return "";
    }

    public static Object[] checkSession(String session) {
        if (session == null) {
            log.warn("user==null||room==null||room.sessionGenKey==null");
            return null;
        }
        try {
            String s = Des.deCrypto(session, Room.sessionGenKey);
            if (s.contains(SPLIT_CHAR)) {
                return s.split(SPLIT_CHAR);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("fail,case:" + e.getMessage());
        }
        return null;
    }

    /**
     * 房间中是否包含这个用户
     *
     * @param userID 用户ID
     * @return true / false
     */
    public boolean isInRoom(int userID) {
        return roomUserList.containsKey(userID);
    }

    /**
     * 用户是否配分配到这个房间
     *
     * @param userID 用户ID
     * @return true / false
     */
    public boolean isBeMatchRoom(int userID) {
        return beMatchedInThisRoomUserList.containsKey(userID);
    }

    /**
     * 房间是否达到最大人数
     *
     * @return boolean
     */
    public boolean isFullUser() {
        return beMatchedInThisRoomUserList.size() >= maxRoomUser;
    }

    public User removeUserFromMatchedList(int userID) {
        return beMatchedInThisRoomUserList.remove(userID);
    }

    public void putUserIntoBeMatchList(User user) {
        beMatchedInThisRoomUserList.put(user.userID, user);
    }

    public void putUserIntoCurrentUserList(User user) {
        roomUserList.put(user.userID, user);
    }

    public User removeUserFromCurrentUserList(int userID) {
        return roomUserList.remove(userID);
    }

    public static void updateRoomServerAddressMap(RoomServiceConfig m_server_reg_room) {
        map.put(m_server_reg_room.gameID, m_server_reg_room);
        log.info("[updateRoomServerAddressMap] "+ m_server_reg_room.toString());
    }
}
